
/* Generated by Interface Builder */

#import "Comb.h"
#import "Instrum.h"
#import <appkit/graphics.h>
#import "Statement.h"

@implementation Comb

+ initialize
{
   	image = [NXImage findImageNamed:"Comb"];
	rvtOffset.x = 3;
	rvtOffset.y = 30;
	inOffset.x = 30;
	inOffset.y = 51;
	pchOffset.x = 52;
	pchOffset.y = 30;
	outOffset.x = 29;
	outOffset.y = 3;
	
	return self;
}

- init
{
	written = NO;
	size.width = 80.;
	size.height = 80.;
	center.x = size.width/2.;
	center.y = size.height/2.;
	strcpy(type,"Comb");
	strcpy(name,"comb");	
	
	rvt = [[Param alloc] init:self :&rvtOffset];
	in = [[Param alloc] init:self :&inOffset];
	pch = [[Param alloc] init:self :&pchOffset];
	out = [[Param alloc] init:self :&outOffset];

	[rvt setValue:".5"];	// set non-"1" defaupch values
	[pch setValue:"440"];	
	[rvt setTitle:"RvbTi:"];
	[pch setTitle:"LpTi"];
	[in setTitle:"Input:"];
	[out setTitle:"Out:"];
		
	paramList = [[List alloc] initCount:5];
	[paramList addObject:rvt];
	[paramList addObject:in];
	[paramList addObject:pch];
	[paramList addObject:out];
	
	[Inst putUgenInList:self];
	
	return self;
}

- remove
{
	id cp,param;
	int i;
							// make sure not connected first 
	for(i = 0; i < ([paramList count]); i++) {	
		param = [paramList objectAt:i];
		if(cp = [param getConnectedParam]) 
			return 0;
	}
							// remove ugen from list
	[Inst removeUgenFromList:self];
	return self;
}

- (NXImage *)getImage
{
	return image;
}

- move:(NXPoint *)newloc
{
	location = *newloc;
	[rvt move:&location];
	[in move:&location];
	[pch move:&location];
	[out move:&location];
	return self;
}

- findParamAtPoint:(NXPoint *)point
{
	NXRect *rect;
	int i;
	id param;
	
	for(i = 0; i < [paramList count]; i++) {
		param = [paramList objectAt:i];
		rect = [param getRect];
		if(NXMouseInRect(point,rect,NO))
			return param;
	}
	return nil;
}

- writeUgen
{
	BOOL ai = NO;	// amplitude input ugen
	char ampVar[10];
	char par[20];
	/* 	for params:
			see if there is input ugen
				if so, grab the output (ug?) and mupchiply it by this
					param value
				if not just use the param value
	 	after all params done, write relevant code into lists
			(declarations, assignments and loop statements)
			i.e. ug? = oscil(,,,,);
		go to output param connected ugen and call its "writeUgen"
	*/
	int i;
	int parent[4];
	id param;
	id ug;
	id nupar;
	char str[50];
	
//	printf("writing ugen %d\n",index);
	sprintf(str,"\tfloat ug%d;\n",index);
	[Inst putVarInList:str];
	sprintf(str,"\tfloat amp%d;\n",index);
	[Inst putVarInList:str];
	sprintf(str,"\tfloat rvt%d;		// reverb time\n",index);
	[Inst putVarInList:str];
	sprintf(str,"\tfloat in%d;\n",index);
	[Inst putVarInList:str];
	sprintf(str,"\tfloat pch%d;\n",index);
	[Inst putVarInList:str];
	sprintf(str,"\tfloat out%d;\n",index);
	[Inst putVarInList:str];
	sprintf(str,"\tfloat loopt%d;		 // loop time\n",index);
	[Inst putVarInList:str];
	sprintf(str,"\tfloat combarr%d[10000];\n",index);
	[Inst putVarInList:str];

	for(i = 0; i < ([paramList count]-1); i++) {	
		param = [paramList objectAt:i];
		if(nupar = [param getConnectedParam]) {
			ug = [nupar getUgen];
			if([ug getWritten] == NO) { 
				parent[i] = [[ug writeUgen] getIndex];
			}
			else  {
				parent[i] = 0;
			}
		}
		else 
			parent[i] = 0;
		
	}

								// reverb time
	strcpy(par,[[paramList objectAt:0] getValue]);
	if(par[0] == 'p' && par[1] == '[')
		sprintf(str,"\trvt%d = %s;\n", index, par);
	else
		sprintf(str,"\trvt%d = %.2f;\n", index, atof(par));
	[Inst putAssignInList:str];
	
								// input sig
	strcpy(par,[[paramList objectAt:1] getValue]);
	if(par[0] == 'p' && par[1] == '[')
		sprintf(str,"\tamp%d = %s;\n", index, par);
	else
		sprintf(str,"\tamp%d = %.2f;\n", index, atof(par));
	[Inst putAssignInList:str];
	
								// pitch
	strcpy(par,[[paramList objectAt:2] getValue]);
	if(par[0] == 'p' && par[1] == '[')
		sprintf(str,"\tloopt%d = 1/%s;\n", index, par);
	else
		sprintf(str,"\tloopt%d = 1/%.2f;\n", index, atof(par));
	[Inst putAssignInList:str];

	if(parent[1]) { 	//  input ugen	
		ai = YES;
		sprintf(str,"\tin%d = %.2f;\n",index, 
			atof([[paramList objectAt:1] getValue]));
		[Inst putAssignInList:str];
		sprintf(str,"\tfloat inai%d;\n",index);
		[Inst putVarInList:str];
		sprintf(str,"\t\tinai%d = amp%d * ug%d;\n",index,  
			index,parent[1]);
		[Inst putLoopInList:str];
	}
	else {				// input preset or default
 		strcpy(par,[[paramList objectAt:0] getValue]);
		if(par[0] == 'p' && par[1] == '[')
			sprintf(str,"\tamp%d = %s;\n", index, par);
		else
			sprintf(str,"\tamp%d = %.2f;\n",index,atof(par));
		[Inst putAssignInList:str];
	}
	if(ai)
		sprintf(ampVar,"inai%d",index);
	else
		sprintf(ampVar,"amp%d",index);
		
	sprintf(str,"\tnsamps = nsamps + (rvt%d * SR);   // add reverbtime to out duration\n",  index, index, index);
	[Inst putAssignInList:str];
		 
						// 	set up comb filter
	sprintf(str, "\tcombset(loopt%d,rvt%d,0,combarr%d);\n",index,index, index);
	[Inst putAssignInList:str];
	
						// 	output amplitude multiplier:
	strcpy(par,[[paramList objectAt:3] getValue]);
	if(par[0] == 'p' && par[1] == '[')
		sprintf(str,"\tout%d = %s;\n",index,par);
	else
		sprintf(str,"\tout%d = %.2f;\n", index, atof([[paramList objectAt:3] getValue]));
	[Inst putAssignInList:str];

	sprintf(str,"\t\tug%d = %s(%s,combarr%d) * out%d;\n", index, name, ampVar, index, index);
	[Inst putLoopInList:str];
	
	written = YES;
	return self;	
}


@end
